package crp.core.security.domain.services.caller;


import com.qwlabs.security.CallerPrincipal;
import com.qwlabs.security.CallerPrincipalLoader;
import crp.core.security.domain.messages.SecurityMessages;
import crp.core.security.domain.services.token.AccessTokenClaims;
import io.quarkus.security.identity.SecurityIdentity;
import io.smallrye.jwt.auth.principal.JWTCallerPrincipal;

import javax.enterprise.context.ApplicationScoped;
import java.security.Principal;
import java.util.Optional;

@ApplicationScoped
public class CallerPrincipalLoaderImpl implements CallerPrincipalLoader {

    @Override
    public CallerPrincipal load(SecurityIdentity identity) {
        return Optional.ofNullable(identity.getPrincipal())
            .map(p -> {
                if (p instanceof JWTCallerPrincipal) {
                    return unwrap((JWTCallerPrincipal) p);
                }
                if (p instanceof Principal) {
                    return new CallerPrincipal(p.getName(),"USER");
                }
                return null;
            })
            .orElseThrow(SecurityMessages.INSTANCE::invalidPrincipal);
    }

    private CallerPrincipal unwrap(JWTCallerPrincipal principal) {
        String id = (String) principal.claim(AccessTokenClaims.CALLER_PRINCIPAL_ID)
            .orElseThrow(SecurityMessages.INSTANCE::invalidPrincipal);
        String type = (String) principal.claim(AccessTokenClaims.CALLER_PRINCIPAL_TYPE)
            .orElseThrow(SecurityMessages.INSTANCE::invalidPrincipal);
        return new CallerPrincipal(id, type);
    }


    public static void main(String[] args) {
        CallerPrincipal callerPrincipal = new CallerPrincipal("admin","USER");

        System.out.println(callerPrincipal instanceof CallerPrincipal);

    }
}
